﻿
/*
*      
*          ┌─┐       ┌─┐
*       ┌──┘ ┴───────┘ ┴──┐
*       │                 │
*       │       ───       │
*       │  ─┬┘       └┬─  │
*       │                 │
*       │       ─┴─       │
*       │                 │
*       └───┐         ┌───┘
*           │         │
*           │         │
*           │         │
*           │         └──────────────┐
*           │                        │
*           │                        ├─┐
*           │                        ┌─┘    
*           │                        │
*           └─┐  ┐  ┌───────┬──┐  ┌──┘         
*             │ ─┤ ─┤       │ ─┤ ─┤         
*             └──┴──┘       └──┴──┘ 
*                 神兽保佑 
*                 代码无BUG! 
*  Author shang
*  2022-07-25 星期一 17:30
*/

using Autofac.Annotation;
using TS.Model;

namespace TS.Services;

[Component]
public class ChilkatService
{
      public string SshShell(SshServer sshServer, string shell)
        {
            string result = "";
            Chilkat.Ssh ssh = new Chilkat.Ssh();

            bool success = ssh.Connect(sshServer.ServerName, sshServer.Port);
            if (success != true)
            {
                return ssh.LastErrorText;
            }

            ssh.IdleTimeoutMs = sshServer.IdleTimeoutMs;
            // Authenticate using login/password:
            success = ssh.AuthenticatePw(sshServer.LoginName, sshServer.PassWord);
            var a= ssh.AuthFailReason;
            if (success != true)
            {
                return ssh.LastErrorText;
            }
            int channelNum;
            channelNum = ssh.OpenSessionChannel();
            if (channelNum < 0)
            {
                return ssh.LastErrorText;
            }
            success = ssh.SendReqPty(channelNum, sshServer.TermType, sshServer.WidthInChars, sshServer.HeightInChars, sshServer.PixWidth, sshServer.PixHeight);
            if (success != true)
            {
                return ssh.LastErrorText;
            }
            success = ssh.SendReqShell(channelNum);
            if (success != true)
            {
                return ssh.LastErrorText;
            }
            // Start a command in the remote shell.  This example
            // will send a "ls" command to retrieve the directory listing.
            success = ssh.ChannelSendString(channelNum, shell, sshServer.Charset);
            if (success != true)
            {
                return ssh.LastErrorText;
            }
            success = ssh.ChannelSendEof(channelNum);
            if (success != true)
            {
                return ssh.LastErrorText;
            }
            // Read whatever output may already be available on the
            // SSH connection.  ChannelReadAndPoll returns the number of bytes
            // that are available in the channel's internal buffer that
            // are ready to be "picked up" by calling GetReceivedText
            // or GetReceivedData.
            // A return value of -1 indicates failure.
            // A return value of -2 indicates a failure via timeout.
            // The ChannelReadAndPoll method waits
            // for data to arrive on the connection usingi the IdleTimeoutMs
            // property setting.  Once the first data arrives, it continues
            // reading but instead uses the pollTimeoutMs passed in the 2nd argument:
            // A return value of -2 indicates a timeout where no data is received.
            int n;
            n = ssh.ChannelReadAndPoll(channelNum, sshServer.PollTimeoutMs);
            if (n < 0)
            {
                return ssh.LastErrorText;
            }

            // Perhaps we did not receive all of the commands output.
            // To make sure,  call ChannelReceiveToClose to accumulate any remaining
            // output until the server's corresponding "channel close" is received.
            //success = ssh.ChannelReceiveToClose(channelNum);
            //if (success != true)
            //{
            //    return ssh.LastErrorText;
            //}
            // Let's pickup the accumulated output of the command:
            string cmdOutput = ssh.GetReceivedText(channelNum, sshServer.Charset);
            if (ssh.LastMethodSuccess != true)
            {
                return ssh.LastErrorText;
            }
            // Display the remote shell's command output:
            result = cmdOutput;
            // Disconnect
            ssh.Disconnect();

            return result;
        }
}
